Skip to content

feat: add a minimal runtime image - #187

Open
baszalmstra wants to merge 5 commits into
mainfrom
feat/minimal-runtime
Open

baszalmstra wants to merge 5 commits into
mainfrom
feat/minimal-runtime

Conversation

@baszalmstra

@baszalmstra baszalmstra commented Sep 9, 2026 •

Copy link
Copy Markdown

The shell-hook example uses Ubuntu for the final stage even though it only needs to run an already-installed environment. This adds ghcr.io/prefix-dev/conda-runtime:glibc-bash, a scratch image with glibc, Bash, and their runtime libraries, without Pixi or a package manager.

I used selected files from a digest-pinned Wolfi image rather than complete APK packages to keep the base small. Local uncompressed sizes are 7.77 MB on amd64 and 7.17 MB on arm64, compared with 78.16 MB for Ubuntu 24.04 on amd64. The image retains upstream component SBOMs, source-path/package mappings, and checksums of the extracted files. These are source-package SBOMs, not an inventory of complete installed APKs or the application's conda environment.

The README and example use the new image. A separate workflow tests both architectures on native runners, exports the tested images, and publishes them as glibc-bash and glibc-bash-<full-git-commit> on main, independently of Pixi releases. Branch-scoped concurrency prevents older runs from overwriting the floating tag. The image has no /bin/sh, coreutils, terminfo, or system CA bundle; the README explains when to include dependencies in the environment or keep using Ubuntu/Debian.

libgcc_s is not included in the base. Applications that need it for glibc thread cancellation or pthread_exit must obtain a discoverable copy from their environment.

Image naming

The runtime goes to a separate conda-runtime package rather than a runtime tag on the pixi package, because this image contains no Pixi and runs any copied conda environment, whatever installed it. The glibc-bash tag names the runtime components it provides, so the name does not commit us to Wolfi as the source distribution.

The new GHCR package needs public visibility after its first publication.

Both final stages stay supported, so the README has a "Choosing a final base image" table comparing conda-runtime and ubuntu:24.04 on size, attack surface, in-container debugging, CA bundles, and base updates. Short version: conda-runtime for small production images where the environment carries everything, Ubuntu or Debian when you want a shell and system packages for debugging or for tooling that expects a distribution layout.

Testing

  • Built and ran the existing example on linux/amd64 and linux/arm64 locally; ARM64 ran under Docker Desktop emulation.
  • Checked shell-hook execution as PID 1, user/group lookup, UTF-8 locale, SQLite, HTTPS, native pthread_exit using the environment's libgcc_s, and file/SBOM provenance with a read-only root filesystem as UID/GID 65532.
  • Exercised the default four-worker Gunicorn command, HTTP responses, worker replacement on SIGHUP, and clean shutdown through Docker SIGTERM on both architectures during the initial runtime implementation.
  • Passed pixi exec --spec actionlint --spec shellcheck actionlint .github/workflows/runtime.yml.
  • Verified the publication commands against a temporary local registry: exported and reloaded both tested images, pushed the per-architecture tags, and assembled the multi-platform manifest. Both published platform configs matched the tested image IDs exactly.

GHCR publication has not been exercised. The separate Pixi deployment guide's Ubuntu example remains valid and is unchanged.

@baszalmstra
baszalmstra requested a review from pavelzw as a code owner September 9, 2026 13:30
Comment on lines +6 to +16
paths:
- Dockerfile.runtime
- .github/workflows/runtime.yml
- example/**
- tests/runtime.py
pull_request:
paths:
- Dockerfile.runtime
- .github/workflows/runtime.yml
- example/**
- tests/runtime.py

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
paths:
- Dockerfile.runtime
- .github/workflows/runtime.yml
- example/**
- tests/runtime.py
pull_request:
paths:
- Dockerfile.runtime
- .github/workflows/runtime.yml
- example/**
- tests/runtime.py
pull_request:

Comment thread Dockerfile.runtime
@@ -0,0 +1,51 @@
FROM cgr.dev/chainguard/wolfi-base@sha256:918a593b8268c222afd4e2c4f06860ac984e60719b4697e4c71d796bc8fcd042 AS source

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do they also have tags that dependabot can update next to the digest? this currently is hard to understand from which version it's coming from

Comment thread Dockerfile.runtime
Comment on lines +4 to +6
bash=5.3-r13 \
ncurses=6.6.20260905-r0 \
ncurses-terminfo-base=6.6.20260905-r0

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how are we planning on updating those?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants